﻿//-----------------------------------------------------------------------
// <copyright file="MapPage.xaml.cs" company="FIT VUT">
//     Copyright (c) FIT VUT. All rights are reserved.
// </copyright>
//----------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Device.Location;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using BookCaching.Data;
using BookCaching.Settings;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Controls.Maps;
using Microsoft.Phone.Shell;
using BookCaching.Knihotoc_WCFService;

namespace BookCaching.Pages
{
    public partial class MapPage : PhoneApplicationPage
    {
        public MapPage()
        {
            this.InitializeComponent();

            (ApplicationBar.Buttons[0] as ApplicationBarIconButton).Text = Localization.LocalizedStrings.Get("CurrentLocationButtonLabel");
            
            currentPositionPushpin.Template = (ControlTemplate)(App.Current.Resources["PushpinCurrentPosition"]);
        }
        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            this.currentPositionPushpin.Location = CurrentSettings.Instance.CurrentPosition;
            CurrentSettings.Instance.CurrentPositionChanged += this.CurrentSettings_CurrentPositionChanged;

            if (NavigationContext.QueryString.ContainsKey("Latitude")
                && NavigationContext.QueryString.ContainsKey("Longitude"))
            {
                this.map.Center = new GeoCoordinate(float.Parse(NavigationContext.QueryString["Latitude"]),
                                                    float.Parse(NavigationContext.QueryString["Longitude"]));
            }
            else
            {                
                this.map.Center = this.currentPositionPushpin.Location;
            }

            // Depends on where we navigate from - MainPage vs. BookDetailPage... modify
            this.map.ZoomLevel = 17.0;
            //this.UpdatePrecision(CurrentSettings.Instance.CurrentPosition);
            ApplicationBar.BackgroundColor = CurrentSettings.Instance.ForegroundColor.Color;
        }

        protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
        {
            CurrentSettings.Instance.CurrentPositionChanged -= this.CurrentSettings_CurrentPositionChanged;
            NavigationService.Navigate(new Uri("/Pages/MainPage.xaml", UriKind.Relative));
        }

        protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
        {
            //CurrentSettings.Instance.CurrentLocationWatcherStop();
            //CurrentSettings.Instance.CurrentPositionChanged -= this.CurrentSettings_CurrentPositionChanged;
        }

        private void CurrentSettings_CurrentPositionChanged(object sender, System.Device.Location.GeoPositionChangedEventArgs<System.Device.Location.GeoCoordinate> e)
        {
            this.currentPositionPushpin.Location = e.Position.Location;
            this.UpdatePrecision(e.Position.Location);
        }

        private void UpdatePrecision(GeoCoordinate location)
        {
            precision.Visibility = Visibility.Collapsed;
            if (location == null)
                return;

            precision.Visibility = Visibility.Visible;
            precision.Locations = new Microsoft.Phone.Controls.Maps.LocationCollection();

            var earthRadius = 6371;
            var lat = location.Latitude * Math.PI / 180.0; //radians 
            var lon = location.Longitude * Math.PI / 180.0; //radians 
            var d = location.HorizontalAccuracy / 1000 / earthRadius; // d = angular distance covered on earths surface 

            for (int x = 0; x <= 360; x++)
            {
                var brng = x * Math.PI / 180.0; //radians 
                var latRadians = Math.Asin(Math.Sin(lat) * Math.Cos(d) + Math.Cos(lat) * Math.Sin(d) * Math.Cos(brng));
                var lngRadians = lon + Math.Atan2(Math.Sin(brng) * Math.Sin(d) * Math.Cos(lat), Math.Cos(d) - Math.Sin(lat) * Math.Sin(latRadians));

                var pt = new GeoCoordinate(180.0 * latRadians / Math.PI, 180.0 * lngRadians / Math.PI);
                precision.Locations.Add(pt);
            }
        }

        private void currentLocationButton_Click_1(object sender, EventArgs e)
        {
            this.map.Center = this.currentPositionPushpin.Location;
            this.map.ZoomLevel = DefaultSettings.Instance.MapZoomLevel;
        }

        private void map_ViewChangeEnd(object sender, Microsoft.Phone.Controls.Maps.MapEventArgs e)
        {            
            GeoCoordinate coordinateUpperLeft = map.ViewportPointToLocation(new Point(0,0));
            GeoCoordinate coordinateBottomRight = map.ViewportPointToLocation(new Point(map.ViewportSize.Width, map.ViewportSize.Height));

            Knihotoc_WP7ServiceClient clientBooks = new Knihotoc_WP7ServiceClient();
            clientBooks.GetBooksByAreaCompleted += Knihotoc_WP7ServiceClient_GetBooksByAreaCompleted;
            clientBooks.GetBooksByAreaAsync(coordinateUpperLeft.Latitude,
                                       coordinateUpperLeft.Longitude,
                                       coordinateBottomRight.Latitude,
                                       coordinateBottomRight.Longitude,
                                       null);

            Knihotoc_WP7ServiceClient clientPlaces = new Knihotoc_WP7ServiceClient();
            clientPlaces.GetPlacesByAreaCompleted += Knihotoc_WP7ServiceClient_GetPlacesByAreaCompleted;
            clientPlaces.GetPlacesByAreaAsync(coordinateUpperLeft.Latitude,
                                       coordinateUpperLeft.Longitude,
                                       coordinateBottomRight.Latitude,
                                       coordinateBottomRight.Longitude,
                                       null);
        }

        void Knihotoc_WP7ServiceClient_GetPlacesByAreaCompleted(object sender, Knihotoc_WCFService.GetPlacesByAreaCompletedEventArgs e)
        {
            try
            {
                foreach (BookCaching.Knihotoc_WCFService.Place place in e.Result)
                {
                    if (place.Address != null)
                    {
                        GeoCoordinate location = new GeoCoordinate((double)place.Address.Lat, (double)place.Address.Lon);
                        bool alreadyAdded = false;

                        for (int i = 0; i < map.Children.Count; ++i)
                        {
                            Pushpin oldPushPin;
                            try
                            {
                                oldPushPin = (Pushpin)map.Children[i];
                                if (oldPushPin.Location == location)
                                {
                                    alreadyAdded = true;
                                    break;
                                }
                            }
                            catch (InvalidCastException)
                            {
                            }
                        }

                        if (!alreadyAdded)
                        {
                            Pushpin newPlacePushpin = new Pushpin();
                            newPlacePushpin.Template = (ControlTemplate)(App.Current.Resources["PushpinPlaceCaffee"]);
                            newPlacePushpin.Name = place.ID.ToString();
                            newPlacePushpin.Tap += newPlacePushpin_Tap;
                            newPlacePushpin.Location = location;
                            map.Children.Add(newPlacePushpin);
                        }
                    }
                }
            }
            finally
            {
                ((Knihotoc_WCFService.Knihotoc_WP7ServiceClient)sender).CloseAsync();
            }
        }        

        void Knihotoc_WP7ServiceClient_GetBooksByAreaCompleted(object sender, Knihotoc_WCFService.GetBooksByAreaCompletedEventArgs e)
        {
            try
            {
                foreach (BookCaching.Knihotoc_WCFService.Book book in e.Result)
                {
                    if (book.BookState == 3)
                    {
                        return;
                    }

                    if (book.Address != null)
                    {
                        ControlTemplate templateToUse;

                        templateToUse = (ControlTemplate)(App.Current.Resources["PushpinBookFound"]);

                        GeoCoordinate location = new GeoCoordinate((double)book.Address.Lat, (double)book.Address.Lon);
                        bool alreadyAdded = false;

                        for (int i = 0; i < map.Children.Count; ++i)
                        {
                            Pushpin oldPushPin;
                            try
                            {
                                oldPushPin = (Pushpin)map.Children[i];
                                if (oldPushPin.Location == location)
                                {
                                    oldPushPin.Template = templateToUse;
                                    alreadyAdded = true;
                                    break;
                                }
                            }
                            catch (InvalidCastException)
                            {
                            }
                        }

                        if (!alreadyAdded)
                        {
                            Pushpin newBookPushpin = new Pushpin();
                            newBookPushpin.Template = templateToUse;
                            newBookPushpin.Name = book.ID.ToString();
                            newBookPushpin.Tap += newBookPushpin_Tap;
                            newBookPushpin.Location = location;
                            map.Children.Add(newBookPushpin);
                        }
                    }
                }
            }
            finally
            {
                ((Knihotoc_WCFService.Knihotoc_WP7ServiceClient)sender).CloseAsync();
            }
        }

        void newPlacePushpin_Tap(object sender, System.Windows.Input.GestureEventArgs e)
        {
            NavigationService.Navigate(new Uri("/Pages/CommonPlaceDetailPage.xaml?PlaceID=" + (sender as Pushpin).Name, UriKind.Relative));
        }

        void newBookPushpin_Tap(object sender, System.Windows.Input.GestureEventArgs e)
        {
            NavigationService.Navigate(new Uri("/Pages/BookDetailPage.xaml?BookID=" + (sender as Pushpin).Name, UriKind.Relative));
        }
    }
}